package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.mongodb.internal.connection.MessageSettings;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.*;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResultVo;
import com.tanhua.model.vo.TodayBestVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.exception.ErrorResult;
import com.tanhua.server.interceptor.UserHolderThreadLocal;
import com.tanhua.utils.Constants;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: test
 * @Create by: JJ菜菜
 * @Date: 2021/12/1 12:44
 */

@Service
public class TanhuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MessageService messageService;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    //指定默认数据
    @Value("${tanhua.default.recommend.users}")
    private String recommendUser;

    // 查询今日佳人数据
    public TodayBestVo findTodayBest() {
        // 获取当前用户id
        Long userId = UserHolderThreadLocal.getId();
        // 调用api查询
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        //
        if(recommendUser == null){
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99d);
        }

        // 查询userInfo
        Long userInfoId = recommendUser.getUserId();
        UserInfo userInfo = userInfoApi.findById(userInfoId);
        // 将userInfo数据和recommendUser数据封装到vo中返回
        TodayBestVo todayBestVo = TodayBestVo.init(userInfo, recommendUser);

        return todayBestVo;
    }

    /**
     * 朋友推荐
     * @param dto
     * @return
     */
    public PageResultVo recommendationByPage(RecommendUserDto dto) {

        Long toUserId = UserHolderThreadLocal.getId();
        // 分页查询数据列表
        Integer page = dto.getPage();
        Integer pagesize = dto.getPagesize();
        // 调用RecommendUser分页查询
        PageResultVo pageResultVo =  recommendUserApi.queryRecommendUserList(page, pagesize, toUserId);
        // 获取userId查询用户详细信息
        List<RecommendUser> recommendUsers = (List<RecommendUser>) pageResultVo.getItems();
        // 判断是否查询到RecommendUser，如果该用户没有好友的话，就返回空
        if (recommendUsers == null || recommendUsers.size() <= 0) {
            return pageResultVo;
        }

        // 使用huTool工具从集合中获取userId集合
        List<Long> ids = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);
        // 封装条件查询userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());

        // 根据用户id批量查询userInfo的用户信息，调用userInfoApi去查询
        Map<Long, UserInfo> map =  userInfoApi.findByIds(userInfo, ids);

        // 将查询到的最佳vo添加到list中
        ArrayList<TodayBestVo> todayBestVos = new ArrayList<>();
        // 循环查询recommendUser
        for (RecommendUser recommendUser : recommendUsers) {

            Long userId = recommendUser.getUserId();
            UserInfo userInfo1 = map.get(userId);
            // 判断是否在userInfo中查询到对应的用户信息
            if(userInfo1 != null){
                // 调用TodayBest的封装返回数据的方法
                TodayBestVo vo = TodayBestVo.init(userInfo1, recommendUser);
                todayBestVos.add(vo);
            }
        }

        // 封装数据返回
        pageResultVo.setItems(todayBestVos);
        return pageResultVo;
    }


    /**
     * 佳人详情
     * @param id
     * @return
     */
    public TodayBestVo personalInfo(Long id) {
        // 查询用户详细和佳人详情表
        UserInfo userInfo = userInfoApi.findById(id);
        // 根据推荐用户和当前登录用户id查询
        RecommendUser recommendUser = recommendUserApi.queryByUserId(id, UserHolderThreadLocal.getId());

        // 构造访客数据
        Visitors visitors = new Visitors();
        visitors.setUserId(id);
        visitors.setVisitorUserId(UserHolderThreadLocal.getId());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitors.setScore(recommendUser.getScore());
        visitorsApi.save(visitors);

        return TodayBestVo.init(userInfo, recommendUser);
    }

    /**
     * 查看陌生人问题
     * @param userId
     * @return
     */
    public String strangerQuestions(Long userId) {

        Question question = questionApi.findByUserId(userId);
        return question == null ? "青山已在，世界我有" : question.getTxt();
    }

    /**
     * 陌生人问题回复
     * @param userId
     * @param reply
     */
    public void replyQuestions(Long userId, String reply) {

        // 1.构建消息数据
        Long currentUserId = UserHolderThreadLocal.getId();
        UserInfo userinfo = userInfoApi.findById(currentUserId);
        // 调用查询陌生人问题方法，获取当前问题
        String questions = strangerQuestions(userId);
        Map map = new HashMap();
        map.put("userId", currentUserId);
        map.put("huanXinId", Constants.HX_USER_PREFIX + currentUserId);
        map.put("nickname", userinfo.getNickname());
        map.put("strangeQuestion", questions);
        map.put("reply", reply);
        // 将map集合转换成json
        String jsonString = JSON.toJSONString(map);
        //2. 调用环信template对象发送消息, 输入接收消息方的环信
        boolean flage = huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, jsonString);
        // 判断消息是否发送成功
        if(!flage){
            throw new BusinessException(ErrorResult.error());
        }

    }


    /**
     * 探花-推荐用户列表
     * @return
     */
    public List<TodayBestVo> queryCardsList() {

        // 1. 调用推荐api数据查询数据列表(排除喜欢/不喜欢的数据)
        List<RecommendUser> recommendUsers = recommendUserApi.queryCardsList(UserHolderThreadLocal.getId(), 10);
        // 2. 判断是否存在，如果不存在就构建默认的数据1， 2， 3
        if(CollUtil.isEmpty(recommendUsers)){
            recommendUsers = new ArrayList<>();
            // 切割指定的默认数据
            String[] userIds = recommendUser.split(",");
            for (String userId : userIds) {
                // 构建默认数据
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(userId));
                recommendUser.setToUserId(UserHolderThreadLocal.getId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUsers.add(recommendUser);
            }
        }
        // 3. 构造vo
        List<Long> userIds = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(null, userIds);

        List<TodayBestVo> vo = new ArrayList<>();
        for (RecommendUser user : recommendUsers) {
            UserInfo userInfo = map.get(user.getUserId());
            if (userInfo != null){
                TodayBestVo todayBestVo = TodayBestVo.init(userInfo, user);
                vo.add(todayBestVo);
            }
        }
        return vo;
    }


    /**
     *  判断是否双向喜欢
     * @param userId
     * @param likeUserId
     * @return
     */
    public boolean isLike(Long userId, Long likeUserId){

        String key = Constants.USER_LIKE_KEY + userId;
        Boolean aBoolean = redisTemplate.opsForSet().isMember(key, likeUserId);
        return aBoolean;
    }

    /**
     * 喜欢
     * @param likeUserId
     */
    public void likeUser(Long likeUserId) {

        // 1. 调用api保存到mongo
        Boolean result = userLikeApi.save(likeUserId, UserHolderThreadLocal.getId(), true);

        if (!result){
            throw new BusinessException(ErrorResult.error());
        }
        // 2. 操作redis，，写入喜欢的数据，删除不喜欢的数据
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + UserHolderThreadLocal.getId(),
                likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + UserHolderThreadLocal.getId(),
                likeUserId.toString());
        // 3. 判断是否双向喜欢
        boolean like = isLike(UserHolderThreadLocal.getId(), likeUserId);
        if (like){
            // 添加好友
            messageService.contacts(likeUserId);
        }
    }

    /**
     * 不喜欢
     * @param likeUserId
     */
    public void notLikeUser(Long likeUserId) {

        // 调用api保存喜欢的数据
        Boolean aBoolean = userLikeApi.save(likeUserId, UserHolderThreadLocal.getId(), false);
        if(!aBoolean){
            throw new BusinessException(ErrorResult.error());
        }
        // 2. 操作redis，写入不喜欢的，删除喜欢的
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + UserHolderThreadLocal.getId(), likeUserId.toString());
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY + UserHolderThreadLocal.getId(), likeUserId.toString());

        // 判断双方是否喜欢，
        if (isLike(UserHolderThreadLocal.getId(), likeUserId)){
            // 不喜欢就删除好友
            messageService.delete(likeUserId);
        }

    }

    /**
     * 搜索附近
     * @param gender
     * @param distant
     * @return
     */
    public List<NearUserVo> searchNear(String gender, String distant) {

        // 1。 调用api查询附近的用户(返回所有用户的id， 包含当前用户的id)
        List<Long> userIds =  userLocationApi.searchNearUser(UserHolderThreadLocal.getId(), Double.valueOf(distant));
        // 2. 判断集合是否为空
        if(CollUtil.isEmpty(userIds)){
            return new ArrayList<>();
        }
        // 3. 调用userInfoapi根据用户id查询用户详细信息
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userInfo, userIds);
        // 4. 构造返回值
        List<NearUserVo> vos = new ArrayList<>();

        for (Long userId : userIds) {
            // 排除当前用户
            if (userId == UserHolderThreadLocal.getId()){
                continue;
            }

            UserInfo info = map.get(userId);
            if(info != null){
                NearUserVo vo = NearUserVo.init(userInfo);
                vos.add(vo);
            }
        }
        return vos;
    }
}
